#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##-- G10 -- S05 ------------------------------------------------------------##
__all__ = []

from .. import formlib as layout
from .. import pilelib as stack
from .. import stackfill as fill
from ..gamelib import info as gi, state, game
from ..hint import CautiousDefaultHint
from ..packlib import place, info as cs
from ..pilelib import move as a_move
from ..utillib.misc import kwdefault

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class Terrace_Talon(stack.WasteTalon):
    """
    Deal _waste_ after card finish on _foundation_.
    """

    def can_deal_cards(self):
        """
        can_deal_cards() -> bool

        Check by Game.talon_deal() if pile can deal more cards. Default is
        after a _foundation_ pile has a card and while waste accepts cards or
        round less than max_rounds.

        :return: deal more cards?
        :rtype: True | False
        """
        return (not self.game.s['foundations'][0].caps['baserank'] == cs.ANY and
               super(Terrace_Talon, self).can_deal_cards())


class NoReserve_AC_RowStack(stack.NotFromReserveBuildMethod,
                            stack.AC_RowStack):
    """
    Build down in rank by alt color from any but _reserve_.
    """
    pass


class Terrace_RowStack(NoReserve_AC_RowStack):
    """
    Build down in rank by alt color from any but _reserve_ after card finish
    on _foundation_. _BOTTOM_IMAGE_ is shade.
    """
    _BOTTOM_IMAGE_ = 'shade'

    def cardsBuild(self, from_stack, cards):
        """
        cardsBuild(from_stack:obj, cards:tup) -> bool

        Check if a _foundation_ pile has a card or no from _reserve_ and
        parent can build with cards from from_stack.

        :param object from_stack: pile playing cards.
        :param tuple cards: cards playing on pile.
        :return: pile can build with cards from played from_stack?
        :rtype: boolean

        seealso:
          Method pysollib.stackcaps.builds for the *capability* check.
        """
        return (self.game.s['foundations'][0].caps['baserank'] != cs.ANY or
                super(Terrace_RowStack, self).cardsBuild(from_stack, cards))

    def move_pile(self, ncards, to_stack, **kw):
        """
        move_pile(ncards:int, to_stack:obj[, frames:int=-1, shadow:int=-1])
          -> None

        Overide move_pile to finish base card on _foundation_ before any play.

        :param integer ncards: move card at ncards deep in pile.
        :param object to_stack: receiving pile.
        """
        if not self.game.s['foundations'][0].caps['baserank'] == cs.ANY:
            super(Terrace_RowStack, self).move_pile(ncards, to_stack, **kw)
        else:
            s = self.game.s
            assert (to_stack in s['foundations'] and not s['wastes'][-1].cards)
            super(Terrace_RowStack, self).move_pile(ncards, to_stack, **kw)
            self.game.talon_deal()


class Wood_RowStack(stack.GapFromWasteBuildMethod, NoReserve_AC_RowStack):
    """
    Build down in rank by alt color from any but _reserve_ after card finish
    on _foundation_. Base play from _waste_. _BOTTOM_IMAGE_ is shade.
    """
    pass


class Terrace(game.Game):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 9 horz S _foundation_. Init deal 1 card on 1st 4, then 1 card must
      finish before next 5 deal 1 card. Build down in rank by alt color wrap.
      Play top. Gap deal 1 card from _waste_.

    _reserve_
      Pile 1 N. Init deal 11 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Build up in rank by alt color from base wrap. No
      card play.
    ------
    :cvar Stack _talon_: Terrace_Talon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_AC_Foundation (max_move=0)
    :cvar Stack _row_: Terrace_RowStack (mod=13, max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=135, name='Terrace', game_type=GT.TERRACE, decks=2,
                    redeals=0, skill_level=SL.MOSTLY_SKILL, version='3.20')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = Terrace_Talon
    _waste_ = stack.WasteStack
    _foundation_ = Wrap(stack.Vary_AC_Foundation, max_move=0)
    _row_ = Wrap(Terrace_RowStack, mod=13, max_move=1)
    _reserve_ = stack.OpenStack
    _hint_ = CautiousDefaultHint

    def _create_game(self, rows=9, playcards=16, **kw):
        l, s = layout.Layout(self), self.s
        maxrows = max(rows, l.NSUITS + 1)
        dx = (maxrows - l.NSUITS) * l.XS / 2
        self.table_size = (2 * l.XM + maxrows * l.XS,
                        l.YM + 2 * l.YS + l._get_stack_height(playcards, l.YS),)
        x, y = l.XM + dx, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 'sw')
        x += l.XS
        s['wastes'].append(self._waste_(x, y, game=self))
        l.set_ncards_text(s['wastes'][-1], 'se', text_format='%D')
        x += 2 * l.XS
        s['reserves'].append(self._reserve_(x, y, game=self,
                          offset=(l.XOFFSET, 0)))
        l.set_ncards_text(s['reserves'][0], 'sw')
        x = l.XM + dx
        y += l.YS
        for i in l.SUITS:
            s['foundations'].append(self._foundation_(x, y, game=self, suit=i))
            x += l.XS
        x = l.XM + (maxrows - rows) * l.XS / 2
        y += l.YS
        for i in range(rows):
            s['rows'].append(self._row_(x, y, game=self))
            x += l.XS
        l.defaultStackGroups()
        return l

    def _start(self, reserves=11, nrows=4, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 11 ea up.
          - s[nrows][:NROWS] 1 ea.

        .. \_start([nrows=4, reserves=6]) -> None
        """
        for i in range(reserves-1):
            self.s['talon'].dealRow(rows=self.s['reserves'], frames=0)
        self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRow(rows=self.s['rows'][:nrows])

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        Fill stack if _row_ when gap from _waste_.

        *Parameters*:
          stack : Stack
            pile just played
        """
        fill.fromWaste(self, stack, self.game.s['rows'])


class QueenOfItaly(Terrace):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 9 horz S _foundation_. Init deal 1 card on 1st 4, then 1 card must
      finish before next 5 deal 1 card. Build down in rank by alt color wrap.
      Play top.

    _reserve_
      Pile 1 N. Init deal 11 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Build up in rank by alt color from base wrap. Top
      play except base.
    ------
    :cvar Stack _talon_: Terrace_Talon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_AC_Foundation
    :cvar Stack _row_: Terrace_RowStack (mod=13, max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=431, name='Queen of Italy', game_type=GT.TERRACE,
                    decks=2, redeals=0, skill_level=SL.BALANCED,
                    version='0.91fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _foundation_ = stack.Vary_AC_Foundation

    def _auto_fill(self, stack):
        """
        Never fill stack.

        *Parameters:
          stack : Stack
            pile just played
        """
        pass


class GeneralsPatience(Terrace):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 9 horz S _foundation_. Init deal 1 card on 1st 4, then 1 card must
      finish before next 5 deal 1 card. Build down in rank by alt color wrap.
      Play top. Gap deal 1 card from _waste_.

    _reserve_
      Pile 1 N. Init deal 13 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Build up in rank by same suit from base wrap. Play
      None.
    ------
    :cvar Stack _talon_: Terrace_Talon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_SS_Foundation (max_move=0)
    :cvar Stack _row_: Terrace_RowStack (mod=13, max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=136, name='Generalʼs Patience', game_type=GT.TERRACE,
                    decks=2, redeals=0, skill_level=SL.MOSTLY_LUCK,
                    version='3.20')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _foundation_ = Wrap(stack.Vary_SS_Foundation, max_move=0)

    def _start(self, reserves=13, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 13 ea up.
          - s[nrows][:NROWS] 1 ea.

        .. \_start([nrows=4, reserves=13]) -> None
        """
        super(GeneralsPatience, self)._start(reserves=reserves, **kw)


class BlondesAndBrunettes(Terrace):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 9 horz S _foundation_. Init deal 1 card. Build down in rank by alt
      color wrap. Play top. Gap deal 1 card from _waste_.

    _reserve_
      Pile 1 N. Init deal 10 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Init deal 1 base card. Build up in rank by alt color
      from base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_AC_Foundation (max_move=0)
    :cvar Stack _row_: NoReserve_RowStack (mod=13, max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=137, name='Blondes and Brunettes',
                    game_type=GT.TERRACE, decks=2, redeals=0,
                    skill_level=SL.MOSTLY_LUCK, version='3.20')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _row_ = Wrap(NoReserve_AC_RowStack, mod=13, max_move=1)

    def _start(self, reserves=10):
        """
        Deal initial cards for new game.
          - s[reserves] 10 ea up.
          - s[nrows] 1 ea.
          - s[foundations] 1 base. save all caps.
        .. \_start([reserves=10]) -> None
        """
        for i in range(reserves):
            self.s['talon'].dealRow(rows=self.s['reserves'])
        self.s['talon'].dealRow()
        base_rank = self.s['talon'].TOPCARD['rank']
        self.s['talon'].dealBaseCards(ncards=1, saveinfo=False)
        self._save_stack_caps(s['foundations'], base_rank=base_rank)


class FallingStar(BlondesAndBrunettes):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 9 horz S _foundation_. Init deal 1 card. Build down in rank by alt
      color wrap. Play top. Gap deal 1 card from _waste_.

    _reserve_
      Pile 1 N. Init deal 11 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Init deal 1 base card. Build up in rank by alt color
      from base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_AC_Foundation (max_move=0)
    :cvar Stack _row_: NoReserve_RowStack (mod=13, max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=138, name='Falling Star', game_type=GT.TERRACE,
                    decks=2, redeals=0, skill_level=SL.MOSTLY_LUCK,
                    version='3.20')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    def _start(self, reserves=11, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 11 ea up.
          - s[nrows] 1 ea.
          - s[foundations] 1 base. save all caps.
        .. \_start([reserves=11]) -> None
        """
        super(FallingStar, self)._start(reserves=reserves, **kw)


class Wood(BlondesAndBrunettes):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 9 horz S _foundation_. Init deal 1 card. Build down in rank by alt
      color wrap. Play top. Base from _waste_.

    _reserve_
      Pile 1 N. Init deal 10 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top on
      _foundation_.

    _foundation_
      Pile 8 S _reserve_. Init deal 1 base card. Build up in rank by alt color
      from base wrap. Play none.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_AC_Foundation (max_move=0)
    :cvar Stack _row_: Wood_RowStack (mod=13, max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=582, name='Wood', game_type=GT.TERRACE, decks=2,
                    redeals=0, skill_level=SL.BALANCED, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _row_ = Wrap(Wood_RowStack, mod=13, max_move=1)

    @state.move_state('fill')
    def _auto_fill(self, stack):
        """
        Never fill stack.

        *Parameters*:
          stack : Stack
           pile just played
        """
        pass


class Signora(Terrace):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 9 horz S _foundation_. Init deal 1 card on 1st 4, then 1 card must
      finish before next 5 deal 1 card. Build down in rank by alt color wrap.
      Play top. Gap deal 1 card from _waste_.

    _reserve_
      Pile 1 N. Init deal 9 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Build up in rank by alt color from base wrap. No
      card play.
    ------
    :cvar Stack _talon_: Terrace_Talon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_AC_Foundation (max_move=0)
    :cvar Stack _row_: Terrace_RowStack (mod=13, max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=499, name='Signora', game_type=GT.TERRACE, decks=2,
                    redeals=0, skill_level=SL.MOSTLY_SKILL, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _start(self, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 11 ea up.
          - s[nrows][:NROWS] 1 ea.

        .. \_start([nrows=LEN, reserves=6]) -> None
        """
        super(Signora, self)._start(nrows=len(self.s['rows']), **kw)


class Madame(Signora):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 10 horz S _foundation_. Init deal 1 card, then 1 card must
      finish before play. Build down in rank by alt color wrap.
      Play top. Gap deal 1 card from _waste_.

    _reserve_
      Pile 1 N. Init deal 15 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Build up in rank by alt color from base wrap. No
      card play.
    ------
    :cvar Stack _talon_: Terrace_Talon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.Vary_AC_Foundation (max_move=0)
    :cvar Stack _row_: Terrace_RowStack (mod=13, max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=500, name='Madame', game_type=GT.TERRACE, decks=3,
                    redeals=0, skill_level=SL.MOSTLY_SKILL, version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    def _create_game(self, **kw):
        kwdefault(kw, rows=10, playcards=20)
        super(Madame, self)._create_game(**kw)

    def _start(self, reserves=15, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 15 ea up.
          - s[nrows][:NROWS] 1 ea.

        .. \_start([nrows=LEN, reserves=15]) -> None
        """
        super(Madame, self)._start(reserves=reserves, **kw)


class MamySusan(BlondesAndBrunettes):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 10 horz S _foundation_. Init deal 4 card. Build down in rank by alt
      color wrap. Play top. Gap deal 1 card from _waste_.

    _reserve_
      Pile 1 N. Init deal 10 open card. Build none. Play top on _foundation_.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Build up in rank by same suit from base wrap. No
      card play.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation (max_move=0)
    :cvar Stack _row_: NoReserve_AC_RowStack (max_move=1)
    :cvar Stack _reserve_: stack.OpenStack
    :cvar Hint _hint_: hint.CautiousDefaultHint
    """
    __info__ = dict(id=533, name='Mamy Susan', game_type=GT.TERRACE,
                    decks=2, redeals=0, skill_level=SL.BALANCED,
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _foundation_ = Wrap(stack.SS_Foundation, max_move=0)
    _row_ = Wrap(NoReserve_AC_RowStack, max_move=1)

    def _create_game(self, **kw):
        kw.setdefault('rows', 10)
        super(MamySusan, self)._create_game(**kw)

    def _start(self, reserves=6, rows=4, **kw):
        """
        Deal initial cards for new game.
          - s[reserves] 6 ea top.
          - s[rows] 4 ea up.

        .. \_start([rows=4, reserves=6]) -> None
        """
        for i in range(reserves - 1):
            self.s['talon'].dealRow(rows=self.s['reserves'], flip=False,
                                    frames=0)
        s['talon'].dealRow(rows=s['reserves'])
        for i in range(rows - 1):
            self.s['talon'].dealRow(frames=0)
        self.s['talon'].dealRow()


class BastilleDay_BastilleStack(stack.Stack):

    def clickHandler(self, event):
        """
        clickHandler(event:obj) -> bool

        A <left-click> will deal_cards().

        :param object event: canvas event.
        :return: event state
        :rtype: True | False | None
        """
        return self.deal_cards(sound=True)

    def rightclickHandler(self, event):
        """
        rightclickHandler(event:obj) -> bool

        Treat <right-click> as <left-click>. Calls clickHandler() method.

        :param object event: canvas event.
        :return: event state
        :rtype: True | False | None
        """
        return self.clickHandler(event)

    def can_deal_cards(self):
        """
        can_deal_cards() -> bool

        Check by deal_cards() if pile can deal more cards. Default is
        while there are cards available.

        :return: deal more cards?
        :rtype: True | False
        """
        if self.game.s['reserves'][-1].cards:
            return 0 < len(self.cards) < 12
        return bool(self.cards)

    @state.move_state('deal')
    def deal_cards(self, sound=False):
        """
        deal_cards([sound:bool=False]) -> None

        Deal cards to _reserve_.

        :keyword boolean sound: sound fx?
        """
        if not self.can_deal_cards():
            return 0
        game = self.game
        if game.can_play_sound:
            game._play_sound('dealwaste')
        game._move_do(a_move.AFlipAndMoveMove(self, game.s['reserves'][-1],
                                              frames=4),
                        reset=True)  # low-level
        return 1

    @property
    def _helpString(self):
        """
        _helpString -> str

        :return: helpful string about pile for its canvas label.
        :rtype: base_string
        """
        return _('Reserve Talon. Deals card for Reserve.')


class BastilleDay(game.Game):
    """
    Finish cards on _foundation_ within a turn.

    _row_
      Pile 8 horz S _foundation_. Init deal 4 card. Build down in rank by alt
      color wrap. Play seq.

    _reserves_
      Pile 2 N [TALON, WASTE].

      TALON
        Init deal E 10 close card. Deals 1 card on _reserve_ WASTE.

      WASTE
        Init deal W 9 open cards. Build none. Play top.

    _talon_
      Pile 1 NW. Deal 1 card on _waste_.

    _waste_
      Pile 1 E _talon_. Init deal 1 card. Build none. Play top.

    _foundation_
      Pile 8 S _reserve_. Build up in rank by same suit from base wrap. No
      card play.
    ------
    :cvar Stack _talon_: stack.WasteTalon
    :cvar Stack _waste_: stack.WasteStack
    :cvar Stack _foundation_: stack.SS_Foundation
    :cvar Stack _row_: stack.AC_RowStack
    :cvar Stack _reserves_: BastilleDay_BastilleStack, stack.OpenStack
    """
    __info__ = dict(id=637, name='Bastille Day', game_type=GT.TERRACE,
                    decks=2, redeals=0, skill_level=SL.BALANCED,
                    version='0.93fc')
    __author__ = 'Skomoroh'
    __version__ = 7.70

    _talon_ = stack.WasteTalon
    _waste_ = stack.WasteStack
    _foundation_ = stack.SS_Foundation
    _row_ = stack.AC_RowStack
    _reserves_ = (BastilleDay_BastilleStack, stack.OpenStack,)

    def _create_game(self, rows=8, playcards=12, **kw):
        l, s = layout.Layout(self), self.s
        self.table_size = (l.XM + 8 * l.XS, l.YM + 2 * l.YS + l.TEXT_HEIGHT +
                            l._get_stack_height(playcards, l.YS),)
        x, y = l.XM, l.YM
        s['talon'] = self._talon_(x, y, game=self)
        l.set_ncards_text(s['talon'], 's')
        x += l.XS
        s['wastes'].append(self._waste_(x, y, game=self))
        l.set_ncards_text(s['wastes'][-1], 's')
        x += 2 * l.XS
        offset = (0, 0)
        for i, _reserve_ in zip(range(2), self._reserves_):
            s['reserves'].append(_reserve_(x, y, game=self, offset=offset))
            l.set_ncards_text(s['reserves'][i], 's')
            x += l.XS
            offset = (l.XOFFSET, 0)
        x = l.XM
        y += l.YS + l.TEXT_HEIGHT
        for i in l.SUITS:
            s['foundations'].append(self._foundation_(x, y, game=self, suit=i))
            x += l.XS
        x = l.XM
        y += l.YS
        for i in range(rows):
            s['rows'].append(stack.AC_RowStack(x, y, self))
            x += l.XS
        l.defaultStackGroups()
        return l

    def _pack_place(self, cards):
        """
        _pack_place(cards:seq(Card ...)) -> seq(Card ...)

        Overide to return KING on bottom by rank, suit, deck for last play.
        """
        return place.MoveToBottom(cards, place.AllKing)

    def _start(self, rows=4, **kw):
        """
        Deal initial cards for new game.
          - s[reserves][:1] 12 ea dn.
          - s[reserves][:1] 9 ea up.
          - s[rows] 4 ea top.

        .. \_start([rows=4]) -> None
        """
        for i in range(12):
            self.s['talon'].dealRow(flip=False, rows=self.s['reserves'][:1],
                                    frames=0)
        for i in range(9):
            self.s['talon'].dealRow(rows=self.s['reserves'][1:], frames=0)
        for i in range(rows - 1):
            self.s['talon'].dealRow(flip=False, frames=0)
        self.s['talon'].dealRow()

    def talon_deal(self, sound=True):
        """
        Overide to deal cards from s.reserve[0] using its deal_cards method
        when demo else default s.talon using its deal_cards method.

        *Keywords*:
          sound : bool
            sound fx?

        *returns*:
          number of cards dealt
        """
        reserve = self.s['reserves'][0]
        if self.is_demo and reserve.can_deal_cards():
            self.move_finish()
            ncards = reserve.deal_cards(sound=sound)
            self.move_finish()
            self.auto_play()
            return ncards
        return super(BastilleDay, self).talon_deal(sound=sound)


PROVIDES = [Terrace, GeneralsPatience, BlondesAndBrunettes, FallingStar,
            QueenOfItaly, Signora, Madame, MamySusan, Wood, BastilleDay]